package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author xiaohai
 * @since 2024-09-15
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final InteractionReplyMapper replyMapper;
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;


    /**
     * 新增问题
     *
     * @param dto
     */
    @Override
    public void saveQuestion(QuestionFormDTO dto) {
        // 1.获得当前用户
        Long userId = UserContext.getUser();

        // 2.把QuestionFormDTO转成InteractionQuestion
        InteractionQuestion question = BeanUtils.copyBean(dto, InteractionQuestion.class);

        // 3.设置userId
        question.setUserId(userId);

        // 4.保存
        save(question);

    }

    /**
     * 分页查询问题
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery query) {
        Long sectionId = query.getSectionId();
        Long courseId = query.getCourseId();
        Boolean onlyMine = query.getOnlyMine();
        Long userId = UserContext.getUser();
        // 1. 健壮性判断
        if (courseId == null && sectionId == null) {
            throw new BizIllegalException("参数有误");
        }
        // 2. 分页查询hidden为false的问题，根据前端的条件进行过滤 投影查询(只查询指定列) 只需要排除描述这个列
        Page<InteractionQuestion> page = lambdaQuery()
                .select(InteractionQuestion.class, q -> !q.getProperty().equals("description"))
                .eq(InteractionQuestion::getHidden, false)
                .eq(courseId != null, InteractionQuestion::getCourseId, courseId)
                .eq(sectionId != null, InteractionQuestion::getSectionId, sectionId)
                .eq(BooleanUtils.isTrue(onlyMine), InteractionQuestion::getUserId, userId)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> questionList = page.getRecords();
        if (CollUtils.isEmpty(questionList)) {
            return PageDTO.empty(page);
        }
        Set<Long> userIds = new HashSet<>();
        Set<Long> answerIds = new HashSet<>();
        for (InteractionQuestion question : questionList) {
            if (!question.getAnonymity()) {
                userIds.add(question.getUserId());          // 不是匿名提问者的id
            }

            answerIds.add(question.getLatestAnswerId());    // 最新一次回答的id
        }
        // 3. 根据latest_answer_id批量查询最近一次回答信息

        answerIds.remove(null);
        Map<Long, InteractionReply> replyMap = new HashMap<>();
        if (CollUtils.isNotEmpty(answerIds)) {
            List<InteractionReply> replyList = replyMapper.selectBatchIds(answerIds);
            if (CollUtils.isNotEmpty(replyList)) {
                //replyMap = replyList.stream().collect(Collectors.toMap(reply -> reply.getId(), reply -> reply));
                for (InteractionReply reply : replyList) {
                    replyMap.put(reply.getId(), reply);
                    // 把不是匿名回答者的id放到userIds集合中
                    if (!reply.getAnonymity()) {
                        userIds.add(reply.getUserId());
                    }
                }
            }
        }
        // 4. 根据user_id批量查询用户（提问者和最近一次回答用户）信息
        userIds.remove(null);   // 防止userIds有null
        List<UserDTO> userList = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userMap = new HashMap<>();
        if (CollUtils.isNotEmpty(userList)) {
            userMap = userList.stream().collect(Collectors.toMap(UserDTO::getId, user -> user));
        }
        // 5. 封装QuestionVO
        List<QuestionVO> voList = new ArrayList<>();
        for (InteractionQuestion question : questionList) {
            // 每遍历一次就封装成一个QuestionVO
            QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
            // 5.1 封装提问者信息 需非匿名的才封装
            if (!question.getAnonymity()) {
                UserDTO user = userMap.get(question.getUserId());
                if (user != null) {
                    vo.setUserName(user.getName());
                    vo.setUserIcon(user.getIcon());
                }
            }
            // 5.2 封装回复信息
            InteractionReply reply = replyMap.get(question.getLatestAnswerId());
            if (reply != null) {
                vo.setLatestReplyContent(reply.getContent());
                if (!reply.getAnonymity()) {    // 不是匿名的回复
                    UserDTO user = userMap.get(reply.getUserId());
                    if (user != null) {
                        vo.setLatestReplyUser(user.getName());
                    }
                }
            }
            voList.add(vo);
        }
        // 6. 返回
        return PageDTO.of(page, voList);
    }

    /**
     * 根据id查询问题
     *
     * @param id
     * @return
     */
    @Override
    public QuestionVO queryQuestionById(Long id) {
        // 1. 根据id查询InteractionQuestion
        InteractionQuestion question = getById(id);
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        // 2. 判断是否是匿名的。如果不是，根据提问者user_id查询用户信息，封装提问者信息
        if (!question.getAnonymity()) {
            UserDTO user = userClient.queryUserById(question.getUserId());
            vo.setUserName(user.getUsername());
            vo.setUserIcon(user.getIcon());
        }
        // 3. 封装QuestionVO
        return vo;
    }

    /**
     * 分页查询管理端问题
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> queryQuestionPageAdmin(QuestionAdminPageQuery query) {
        LocalDateTime beginTime = query.getBeginTime();
        LocalDateTime endTime = query.getEndTime();
        String courseName = query.getCourseName();
        Integer status = query.getStatus();
        // 1. 处理课程名称，获得课程id
        List<Long> courseIds = null;
        if (StringUtils.isNotEmpty(courseName)) {
            courseIds = searchClient.queryCoursesIdByName(courseName);
            if (CollUtils.isEmpty(courseIds)) {
                return PageDTO.empty(0L, 0L);
            }
        }
        // 2. 分页查询问题，根据前端传过来的参数进行过滤
        Page<InteractionQuestion> page = lambdaQuery()
                .eq(status != null, InteractionQuestion::getStatus, status)
                .gt(beginTime != null, InteractionQuestion::getCreateTime, beginTime)
                .lt(endTime != null, InteractionQuestion::getCreateTime, endTime)
                .in(CollUtils.isNotEmpty(courseIds), InteractionQuestion::getCourseId, courseIds)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> questionList = page.getRecords();
        if (CollUtils.isEmpty(questionList)) {
            return PageDTO.empty(page);
        }
        /*
          userIds  用户id集合
          courseIdsSet 课程id集合
          cataIds  章节id集合
         */
        Set<Long> userIds = new HashSet<>();
        Set<Long> courseIdsSet = new HashSet<>();
        Set<Long> cataIds = new HashSet<>();
        for (InteractionQuestion question : questionList) {
            userIds.add(question.getUserId());
            courseIdsSet.add(question.getCourseId());
            cataIds.add(question.getChapterId());
        }
        // 3. 根据userId查询用户信息
        Map<Long, UserDTO> userMap = new HashMap<>();
        List<UserDTO> userList = userClient.queryUserByIds(userIds);
        if (CollUtils.isNotEmpty(userList)) {
            userMap = userList.stream().collect(Collectors.toMap(UserDTO::getId, user -> user));
        }
        // 4. 根据courseId查询课程信息
        Map<Long, CourseSimpleInfoDTO> courseMap = new HashMap<>();
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIdsSet);
        if (CollUtils.isNotEmpty(courseList)) {
            courseMap = courseList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, course -> course));
        }
        // 5. 根据章节id查询章节信息
        List<CataSimpleInfoDTO> cataList = catalogueClient.batchQueryCatalogue(cataIds);
        Map<Long, CataSimpleInfoDTO> cataMap = new HashMap<>();
        if (CollUtils.isNotEmpty(cataList)) {
            cataMap = cataList.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, cata -> cata));
        }
        // 6. 遍历问题列表，封装VO
        List<QuestionAdminVO> voList = new ArrayList<>();
        for (InteractionQuestion question : questionList) {
            // 每遍历一次就要封装成一个VO
            QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
            //   6.1 封装用户数据
            UserDTO user = userMap.get(question.getUserId());
            if (user != null) {
                vo.setUserName(user.getName());
            }
            //   6.2 封装课程数据和类别数据(处理课程的类别)
            CourseSimpleInfoDTO course = courseMap.get(question.getCourseId());
            if (course != null) {
                vo.setCourseName(course.getName());
                String categoryNames = categoryCache.getCategoryNames(course.getCategoryIds());
                vo.setCategoryName(categoryNames);
            }
            //   6.3 封装章节数据
            CataSimpleInfoDTO chapter = cataMap.get(question.getChapterId());
            if (chapter != null) {
                vo.setChapterName(chapter.getName());
            }
            CataSimpleInfoDTO section = cataMap.get(question.getSectionId());
            if (section != null) {
                vo.setSectionName(section.getName());
            }
            voList.add(vo);
        }

        //  7. 返回
        return PageDTO.of(page, voList);
    }
}
